#pragma once

#include<iostream>
#include<stdarg.h>
#include<time.h>
#include<string>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>


#define SIZE 1024
#define Logfile "log.txt"
enum Error_code
{
    Info = 1,
    Debug,
    Waring,
    Error,
    Fatal
};

enum Print
{
    Screen = 1,
    Onefile,
    Classfile
};

class Log
{
public:
Log(int method = Screen,const char* path = "./log")
:_printMethod(method),
_path(path)
{}


static std::string leveltoString(int level)
{
    switch(level)
    {
        case Info: return "Info";
        case Debug: return "Debug";
        case Waring: return "Waring";
        case Error: return "Error";
        case Fatal: return "Fatal";
        default: return "None";
    }
}

// void Logmessage(int level, char *format, ...)
// {
//     time_t t = time(nullptr);
//     struct tm *ctime = localtime(&t);
//     char leftbuffer[SIZE];
//     snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", leveltoString(level).c_str(),\
//      ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

//     va_list s;
//     va_start(s, format);
//     char rightbuffer[SIZE];
//     vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
//     va_end(s);

//     //格式，默认部分+自定义部分
//     char logtxt[SIZE*2];
//     snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);
//     printLog(level, logtxt);
// }

void printLog(int level, const std::string& logtxt)
{
    switch (_printMethod)
    {
        case Screen:
        {
            std::cout<<logtxt<<std::endl;
            break;
        }
        case Onefile:
        {
            printOneFile(logtxt);
            break;
        }
        case Classfile:
        {
            printClassFile(level, logtxt);
            break;
        }
        default:
            break;
    }
}

void printOneFile(const std::string& logtxt, const std::string &logname = Logfile)
{
    int fd = open(logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
    if(fd < 0)
    {
        std::cout<<"open error"<<std::endl;
        exit(errno);
    }
    write(fd, logtxt.c_str(), logtxt.size());
    close(fd);
}

void printClassFile(int level, const std::string& logtxt)
{
    std::string filename = filename;
    filename += ".";
    filename += leveltoString(level);
    printOneFile(logtxt, filename);
}


~Log()
{}

void operator()(int level, char *format, ...)
{
    time_t t = time(nullptr);
    struct tm *ctime = localtime(&t);
    char leftbuffer[SIZE];
    snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", leveltoString(level).c_str(),\
     ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

    va_list s;
    va_start(s, format);
    char rightbuffer[SIZE];
    vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
    va_end(s);

    //格式，默认部分+自定义部分
    char logtxt[SIZE*2];
    snprintf(logtxt, sizeof(logtxt), "%s %s", leftbuffer, rightbuffer);
    printLog(level, logtxt);
}

private:
    int _printMethod;
    const char *_path;
};



// int sum(int n, ...)
// {
//     va_list s;
//     va_start(s, n);

//     int sum = 0;
//     while(n)
//     {
//         sum += va_arg(s, int);
//         n--;
//     }
//     va_end(s);
//     return sum;
// }